package com.inspectortime.repository;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import com.inspectortime.domain.EmailTemplate;
import com.inspectortime.domain.HomeBuyer;
import com.inspectortime.domain.Inspection;
import com.inspectortime.domain.Inspector;
import com.inspectortime.domain.InspectorCompany;
import com.inspectortime.domain.OptionalService;
import com.inspectortime.domain.Property;
import com.inspectortime.domain.RealEstateAgent;
import com.inspectortime.domain.ScheduleRule;
import com.inspectortime.domain.Scheduler;
import com.inspectortime.domain.ZipCodeGeoData;
import com.inspectortime.domain.billing.Invoice;
import com.inspectortime.domain.billing.InvoiceLineItem;
import com.inspectortime.domain.billing.Payment;
import com.inspectortime.domain.billing.PaymentLineItem;
import com.inspectortime.domain.billing.PaymentSourceType;
import com.inspectortime.domain.impl.EmailTemplateImpl;
import com.inspectortime.domain.impl.HomeBuyerImpl;
import com.inspectortime.domain.impl.InspectionImpl;
import com.inspectortime.domain.impl.InspectorCompanyImpl;
import com.inspectortime.domain.impl.InspectorImpl;
import com.inspectortime.domain.impl.OptionalServiceImpl;
import com.inspectortime.domain.impl.PropertyImpl;
import com.inspectortime.domain.impl.RealEstateAgentImpl;
import com.inspectortime.domain.impl.ScheduleRuleImpl;
import com.inspectortime.domain.impl.SchedulerImpl;
import com.inspectortime.domain.impl.ZipCodeGeoDataImpl;
import com.inspectortime.domain.pricing.BaseFeeWithAdjustersCalculator;
import com.inspectortime.domain.type.Address;
import com.inspectortime.domain.type.FrequencyType;
import com.inspectortime.domain.type.Name;

/**
 * Factory for all "rich" application domain objects
 * @author mkvalsvik
 *
 */
public class Factory {

	public Factory() {
	}

	public ZipCodeGeoData createZipCodeGeoData() {
		return new ZipCodeGeoDataImpl();
	}
	
	public Inspection createInspection() {
		Inspection inspection = new InspectionImpl(this.createHomeBuyer(), this.createProperty(), null);
		return inspection;
	}
	
	public Inspection createInspection(Inspector inspector) {
		Inspection inspection = new InspectionImpl(this.createHomeBuyer(), this.createProperty(), inspector);
		return inspection;
	}
	
	public Inspection createInspection(HomeBuyer homeBuyer, Property property, Inspector inspector) {
		Inspection inspection = new InspectionImpl(homeBuyer, property, inspector);
		return inspection;
	}

	public HomeBuyer createHomeBuyer() {
		
		HomeBuyer buyer = new HomeBuyerImpl();

		// WORKAROUND: The homeBuyer.name property will be null unless it is initialized with a property value
		Name name = new Name();
		name.setFirst("");
		buyer.setName(name);

		// WORKAROUND: The homeBuyer.address property will be null unless it is initialized with a property value
		Address address = new Address();
		address.setStreet1("");
		buyer.setAddress(address);
		return buyer;
	}
	
	public Inspector createInspector() {
		return this.createInspector(this.createInspectorCompany());
	}
	
	public Scheduler createScheduler() {
		return this.createScheduler(this.createInspectorCompany());
	}
	
	public Scheduler createScheduler(InspectorCompany company) {
		Scheduler scheduler = new SchedulerImpl(new Name());
		scheduler.setCompany(company);
		//scheduler.setStatus(User.Status.ACTIVE);
		company.addScheduler(scheduler);
		return scheduler;
	}
	
	public EmailTemplate createEmailTemplate(String templateName, InspectorCompany company) {
		EmailTemplate template = new EmailTemplateImpl();
		template.setName(templateName);
		template.setCompany(company);
		company.getEmailTemplates().add(template);
		return template;
	}
	
	public Inspector createInspector(InspectorCompany company) {
		Inspector inspector = new InspectorImpl(new Name());
		//inspector.setStatus(User.Status.ACTIVE);
		inspector.setCompany(company);
		
		//build a default set of scheduleRules
		List<ScheduleRule> scheduleRules = new ArrayList<ScheduleRule>();
		ScheduleRule scheduleRule = this.createScheduleRule();
		scheduleRule.setFrequencyType(FrequencyType.DAY_OF_WEEK);
		scheduleRule.setUnits(new int[] {Calendar.MONDAY, Calendar.WEDNESDAY, Calendar.FRIDAY});
		scheduleRule.setAvailable(true);
		scheduleRule.setStartHour(9);
		scheduleRule.setStartMinute(0);
		scheduleRule.setEndHour(12);
		scheduleRule.setEndMinute(30);
		scheduleRules.add(scheduleRule);
		
		inspector.setScheduleRules(scheduleRules);
		
		company.addInspector(inspector);
		return inspector;
	}
	
	public InspectorCompany createInspectorCompany() {
		InspectorCompany company = new InspectorCompanyImpl(new Address());
		return company;
	}
	public Property createProperty() {
		Property property = new PropertyImpl(new Address());
		return property;
	}
	public RealEstateAgent createRealEstateAgent() {
		RealEstateAgent obj = new RealEstateAgentImpl(new Name());
		return obj;
	}
	
	public OptionalService createOptionalService() {
		OptionalService obj = new OptionalServiceImpl();
		return obj;
	}
	
	public Payment createPayment(PaymentSourceType type) {
		Payment payment = new Payment(type);
		return payment;
	}
	
	public Invoice createInvoice() {
		return new Invoice();
	}
	
	public InvoiceLineItem createInvoiceLineItem() {
		return new InvoiceLineItem();
	}
	
	public ScheduleRule createScheduleRule() {
		ScheduleRule scheduleRule = new ScheduleRuleImpl();
		return scheduleRule;
	}

	public BaseFeeWithAdjustersCalculator createBaseFeeWithAdjustersCalculator() {
		return new BaseFeeWithAdjustersCalculator();
	}
}
